﻿

import pygame
import sys
import math
import random
from pygame.locals import *

# 初始化 Pygame
pygame.init()

# 游戏常量
WIDTH, HEIGHT = 800, 600
FPS = 60
GRAVITY = 0.5
ELASTICITY = 0.8
FRICTION = 0.99

# 颜色定义
SKY_BLUE = (135, 206, 235)
GREEN = (34, 139, 34)
BROWN = (139, 69, 19)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
PIG_COLOR = (0, 128, 0)

# 创建游戏窗口
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('愤怒的小鸟')
clock = pygame.time.Clock()

# 加载图像
def load_images():
    images = {}
    try:
        # 小鸟图像
        images['red_bird'] = pygame.Surface((30, 30), pygame.SRCALPHA)
        pygame.draw.circle(images['red_bird'], RED, (15, 15), 15)
        pygame.draw.circle(images['red_bird'], WHITE, (10, 10), 5)
        pygame.draw.circle(images['red_bird'], BLACK, (10, 10), 2)
        pygame.draw.polygon(images['red_bird'], YELLOW, [(25, 15), (35, 15), (30, 20)])
        
        images['yellow_bird'] = pygame.Surface((30, 30), pygame.SRCALPHA)
        pygame.draw.circle(images['yellow_bird'], YELLOW, (15, 15), 15)
        pygame.draw.circle(images['yellow_bird'], WHITE, (10, 10), 5)
        pygame.draw.circle(images['yellow_bird'], BLACK, (10, 10), 2)
        pygame.draw.polygon(images['yellow_bird'], ORANGE, [(25, 15), (35, 15), (30, 20)])
        
        images['blue_bird'] = pygame.Surface((30, 30), pygame.SRCALPHA)
        pygame.draw.circle(images['blue_bird'], BLUE, (15, 15), 15)
        pygame.draw.circle(images['blue_bird'], WHITE, (10, 10), 5)
        pygame.draw.circle(images['blue_bird'], BLACK, (10, 10), 2)
        pygame.draw.polygon(images['blue_bird'], YELLOW, [(25, 15), (35, 15), (30, 20)])
        
        # 猪图像
        images['pig'] = pygame.Surface((40, 40), pygame.SRCALPHA)
        pygame.draw.circle(images['pig'], PIG_COLOR, (20, 20), 20)
        pygame.draw.circle(images['pig'], (0, 100, 0), (15, 15), 5)
        pygame.draw.circle(images['pig'], (0, 100, 0), (25, 15), 5)
        pygame.draw.circle(images['pig'], BLACK, (15, 15), 2)
        pygame.draw.circle(images['pig'], BLACK, (25, 15), 2)
        pygame.draw.ellipse(images['pig'], (255, 100, 100), (12, 25, 16, 8))
        
        # 障碍物图像
        images['wood'] = pygame.Surface((50, 20), pygame.SRCALPHA)
        pygame.draw.rect(images['wood'], BROWN, (0, 0, 50, 20))
        pygame.draw.rect(images['wood'], (101, 67, 33), (0, 0, 50, 20), 2)
        
        images['stone'] = pygame.Surface((50, 50), pygame.SRCALPHA)
        pygame.draw.circle(images['stone'], (150, 150, 150), (25, 25), 25)
        pygame.draw.circle(images['stone'], (120, 120, 120), (25, 25), 25, 2)
        
        # 弹弓图像
        images['slingshot'] = pygame.Surface((50, 100), pygame.SRCALPHA)
        pygame.draw.line(images['slingshot'], BROWN, (10, 0), (10, 100), 10)
        pygame.draw.line(images['slingshot'], BROWN, (40, 0), (40, 100), 10)
        pygame.draw.arc(images['slingshot'], BROWN, (0, 70, 50, 30), 0, math.pi, 10)
        
        # 背景
        images['background'] = pygame.Surface((WIDTH, HEIGHT))
        images['background'].fill(SKY_BLUE)
        pygame.draw.rect(images['background'], GREEN, (0, HEIGHT - 100, WIDTH, 100))
        
        # 云朵
        for _ in range(5):
            x = random.randint(0, WIDTH)
            y = random.randint(50, 200)
            size = random.randint(30, 70)
            pygame.draw.circle(images['background'], WHITE, (x, y), size)
            pygame.draw.circle(images['background'], WHITE, (x + size//2, y - size//3), size//1.5)
            pygame.draw.circle(images['background'], WHITE, (x + size, y), size//1.2)
        
    except Exception as e:
        print(f"无法加载图像: {e}")
        # 创建简单的替代图像
        images['red_bird'] = pygame.Surface((30, 30))
        images['red_bird'].fill(RED)
        images['yellow_bird'] = pygame.Surface((30, 30))
        images['yellow_bird'].fill(YELLOW)
        images['blue_bird'] = pygame.Surface((30, 30))
        images['blue_bird'].fill(BLUE)
        images['pig'] = pygame.Surface((40, 40))
        images['pig'].fill(PIG_COLOR)
        images['wood'] = pygame.Surface((50, 20))
        images['wood'].fill(BROWN)
        images['stone'] = pygame.Surface((50, 50))
        images['stone'].fill((150, 150, 150))
        images['slingshot'] = pygame.Surface((50, 100))
        images['slingshot'].fill(BROWN)
        images['background'] = pygame.Surface((WIDTH, HEIGHT))
        images['background'].fill(SKY_BLUE)
    
    return images

# 加载字体
font = pygame.font.SysFont('simhei', 36)
small_font = pygame.font.SysFont('simhei', 24)

class Bird:
    def __init__(self, x, y, bird_type='red'):
        self.x = x
        self.y = y
        self.radius = 15
        self.vx = 0
        self.vy = 0
        self.bird_type = bird_type
        self.active = True
        self.launched = False
        self.trail = []
        self.max_trail = 20
        self.special_ability_used = False
    
    def update(self):
        if not self.active:
            return
        
        # 应用重力
        self.vy += GRAVITY
        
        # 更新位置
        self.x += self.vx
        self.y += self.vy
        
        # 记录轨迹
        self.trail.append((int(self.x), int(self.y)))
        if len(self.trail) > self.max_trail:
            self.trail.pop(0)
        
        # 边界检查
        if self.x < self.radius:
            self.x = self.radius
            self.vx = -self.vx * ELASTICITY
        elif self.x > WIDTH - self.radius:
            self.x = WIDTH - self.radius
            self.vx = -self.vx * ELASTICITY
        
        if self.y > HEIGHT - 100 - self.radius:
            self.y = HEIGHT - 100 - self.radius
            self.vy = -self.vy * ELASTICITY
            self.vx *= FRICTION
            
            # 如果速度很小，停止运动
            if abs(self.vy) < 0.5:
                self.vy = 0
            if abs(self.vx) < 0.5:
                self.vx = 0
                self.active = False
        
        # 摩擦力
        self.vx *= FRICTION
        self.vy *= FRICTION
    
    def draw(self, surface, images):
        if not self.active:
            return
        
        # 绘制轨迹
        for i, (trail_x, trail_y) in enumerate(self.trail):
            alpha = int(255 * (i / len(self.trail)))
            color = (255, 255, 255, alpha)
            pygame.draw.circle(surface, color, (trail_x, trail_y), 3)
        
        # 绘制小鸟
        bird_img = images[f'{self.bird_type}_bird']
        surface.blit(bird_img, (self.x - bird_img.get_width() // 2, self.y - bird_img.get_height() // 2))
    
    def use_special_ability(self):
        if self.special_ability_used or not self.launched:
            return
        
        self.special_ability_used = True
        
        if self.bird_type == 'yellow':
            # 黄色小鸟：加速
            self.vx *= 1.5
            self.vy *= 1.5
        elif self.bird_type == 'blue':
            # 蓝色小鸟：分裂
            return [
                Bird(self.x, self.y, 'blue'),
                Bird(self.x, self.y, 'blue')
            ]
        
        return []

class Pig:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.radius = 20
        self.active = True
    
    def update(self):
        pass
    
    def draw(self, surface, images):
        if not self.active:
            return
        pig_img = images['pig']
        surface.blit(pig_img, (self.x - pig_img.get_width() // 2, self.y - pig_img.get_height() // 2))
    
    def check_collision(self, bird):
        if not self.active or not bird.active:
            return False
        
        distance = math.sqrt((self.x - bird.x)**2 + (self.y - bird.y)**2)
        return distance < self.radius + bird.radius

class Block:
    def __init__(self, x, y, block_type='wood'):
        self.x = x
        self.y = y
        self.width = 50
        self.height = 20 if block_type == 'wood' else 50
        self.block_type = block_type
        self.active = True
        self.health = 2 if block_type == 'wood' else 4
        self.rotation = 0
        self.vx = 0
        self.vy = 0
    
    def update(self):
        if not self.active:
            return
        
        # 应用重力
        self.vy += GRAVITY
        
        # 更新位置
        self.x += self.vx
        self.y += self.vy
        
        # 边界检查
        if self.y > HEIGHT - 100 - self.height:
            self.y = HEIGHT - 100 - self.height
            self.vy = -self.vy * ELASTICITY
            self.vx *= FRICTION
            
            # 如果速度很小，停止运动
            if abs(self.vy) < 0.5:
                self.vy = 0
            if abs(self.vx) < 0.5:
                self.vx = 0
        
        # 摩擦力
        self.vx *= FRICTION
        self.vy *= FRICTION
    
    def draw(self, surface, images):
        if not self.active:
            return
        
        img = images[self.block_type]
        
        # 创建旋转后的图像
        rotated_img = pygame.transform.rotate(img, self.rotation)
        surface.blit(rotated_img, (self.x - rotated_img.get_width() // 2, self.y - rotated_img.get_height() // 2))
    
    def check_collision(self, bird):
        if not self.active or not bird.active:
            return False
        
        # 简单的矩形与圆形碰撞检测
        closest_x = max(self.x - self.width // 2, min(bird.x, self.x + self.width // 2))
        closest_y = max(self.y - self.height // 2, min(bird.y, self.y + self.height // 2))
        
        distance = math.sqrt((bird.x - closest_x)**2 + (bird.y - closest_y)**2)
        return distance < bird.radius
    
    def take_damage(self):
        self.health -= 1
        if self.health <= 0:
            self.active = False
            return True
        return False

class Slingshot:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.pulled = False
        self.pull_x = 0
        self.pull_y = 0
    
    def draw(self, surface, images):
        slingshot_img = images['slingshot']
        surface.blit(slingshot_img, (self.x - slingshot_img.get_width() // 2, self.y - slingshot_img.get_height()))
        
        # 绘制弹弓带
        if self.pulled:
            pygame.draw.line(surface, BROWN, (self.x - 10, self.y - 70), (self.pull_x, self.pull_y), 5)
            pygame.draw.line(surface, BROWN, (self.x + 10, self.y - 70), (self.pull_x, self.pull_y), 5)

class Game:
    def __init__(self):
        self.images = load_images()
        self.level = 1
        self.score = 0
        self.birds = []
        self.pigs = []
        self.blocks = []
        self.slingshot = Slingshot(100, HEIGHT - 100)
        self.current_bird = None
        self.game_state = "ready"  # ready, aiming, launched, level_complete, game_over
        self.level_complete_timer = 0
        self.reset_level()
    
    def reset_level(self):
        self.birds = []
        self.pigs = []
        self.blocks = []
        
        # 创建小鸟
        bird_types = ['red', 'yellow', 'blue']
        for i in range(3):
            self.birds.append(Bird(self.slingshot.x, self.slingshot.y - 50, bird_types[i]))
        
        self.current_bird = self.birds[0]
        self.game_state = "ready"
        
        # 创建关卡
        if self.level == 1:
            self.create_level1()
        elif self.level == 2:
            self.create_level2()
        elif self.level == 3:
            self.create_level3()
    
    def create_level1(self):
        # 创建猪
        self.pigs.append(Pig(600, HEIGHT - 150))
        
        # 创建障碍物
        self.blocks.append(Block(500, HEIGHT - 150, 'wood'))
        self.blocks.append(Block(550, HEIGHT - 150, 'wood'))
        self.blocks.append(Block(600, HEIGHT - 150, 'wood'))
        self.blocks.append(Block(650, HEIGHT - 150, 'wood'))
        self.blocks.append(Block(700, HEIGHT - 150, 'wood'))
    
    def create_level2(self):
        # 创建猪
        self.pigs.append(Pig(650, HEIGHT - 150))
        self.pigs.append(Pig(700, HEIGHT - 150))
        
        # 创建障碍物
        self.blocks.append(Block(500, HEIGHT - 150, 'wood'))
        self.blocks.append(Block(550, HEIGHT - 150, 'wood'))
        self.blocks.append(Block(600, HEIGHT - 150, 'wood'))
        self.blocks.append(Block(650, HEIGHT - 150, 'wood'))
        self.blocks.append(Block(700, HEIGHT - 150, 'wood'))
        
        self.blocks.append(Block(550, HEIGHT - 200, 'wood'))
        self.blocks.append(Block(600, HEIGHT - 200, 'wood'))
        self.blocks.append(Block(650, HEIGHT - 200, 'wood'))
        
        self.blocks.append(Block(600, HEIGHT - 250, 'wood'))
    
    def create_level3(self):
        # 创建猪
        self.pigs.append(Pig(650, HEIGHT - 150))
        self.pigs.append(Pig(700, HEIGHT - 150))
        self.pigs.append(Pig(600, HEIGHT - 250))
        
        # 创建障碍物
        self.blocks.append(Block(500, HEIGHT - 150, 'stone'))
        self.blocks.append(Block(550, HEIGHT - 150, 'stone'))
        self.blocks.append(Block(600, HEIGHT - 150, 'stone'))
        self.blocks.append(Block(650, HEIGHT - 150, 'stone'))
        self.blocks.append(Block(700, HEIGHT - 150, 'stone'))
        
        self.blocks.append(Block(550, HEIGHT - 200, 'wood'))
        self.blocks.append(Block(600, HEIGHT - 200, 'wood'))
        self.blocks.append(Block(650, HEIGHT - 200, 'wood'))
        
        self.blocks.append(Block(600, HEIGHT - 250, 'wood'))
        self.blocks.append(Block(600, HEIGHT - 300, 'wood'))
    
    def update(self):
        # 更新所有对象
        for bird in self.birds:
            bird.update()
        
        for block in self.blocks:
            block.update()
        
        # 检查碰撞
        self.check_collisions()
        
        # 检查游戏状态
        self.check_game_state()
        
        # 更新关卡完成计时器
        if self.game_state == "level_complete":
            self.level_complete_timer += 1
            if self.level_complete_timer > 120:  # 2秒后进入下一关
                self.level += 1
                if self.level > 3:
                    self.game_state = "game_over"
                else:
                    self.reset_level()
    
    def check_collisions(self):
        # 小鸟与障碍物碰撞
        for bird in self.birds:
            if not bird.active:
                continue
                
            for block in self.blocks:
                if block.active and block.check_collision(bird):
                    # 计算碰撞后的速度
                    dx = bird.x - block.x
                    dy = bird.y - block.y
                    distance = max(0.1, math.sqrt(dx*dx + dy*dy))
                    
                    # 标准化方向
                    dx /= distance
                    dy /= distance
                    
                    # 计算相对速度
                    dot_product = bird.vx * dx + bird.vy * dy
                    
                    # 应用碰撞力
                    bird.vx = ELASTICITY * (bird.vx - 2 * dot_product * dx)
                    bird.vy = ELASTICITY * (bird.vy - 2 * dot_product * dy)
                    
                    # 障碍物受到伤害
                    if block.take_damage():
                        self.score += 100
        
        # 小鸟与猪碰撞
        for bird in self.birds:
            if not bird.active:
                continue
                
            for pig in self.pigs:
                if pig.active and pig.check_collision(bird):
                    pig.active = False
                    self.score += 500
                    bird.vx *= 0.5
                    bird.vy *= 0.5
    
    def check_game_state(self):
        # 检查是否所有猪都被消灭
        pigs_alive = any(pig.active for pig in self.pigs)
        
        # 检查是否所有小鸟都使用完毕
        birds_active = any(bird.active for bird in self.birds)
        
        if not pigs_alive:
            self.game_state = "level_complete"
            self.level_complete_timer = 0
        elif not birds_active and not pigs_alive:
            self.game_state = "level_complete"
            self.level_complete_timer = 0
        elif not birds_active and pigs_alive:
            self.game_state = "game_over"
    
    def draw(self):
        # 绘制背景
        screen.blit(self.images['background'], (0, 0))
        
        # 绘制地面
        pygame.draw.rect(screen, GREEN, (0, HEIGHT - 100, WIDTH, 100))
        
        # 绘制弹弓
        self.slingshot.draw(screen, self.images)
        
        # 绘制障碍物
        for block in self.blocks:
            block.draw(screen, self.images)
        
        # 绘制猪
        for pig in self.pigs:
            pig.draw(screen, self.images)
        
        # 绘制小鸟
        for bird in self.birds:
            bird.draw(screen, self.images)
        
        # 绘制UI
        score_text = font.render(f"分数: {self.score}", True, WHITE)
        screen.blit(score_text, (20, 20))
        
        level_text = font.render(f"关卡: {self.level}/3", True, WHITE)
        screen.blit(level_text, (WIDTH - level_text.get_width() - 20, 20))
        
        birds_left = sum(1 for bird in self.birds if not bird.launched)
        birds_text = small_font.render(f"剩余小鸟: {birds_left}", True, WHITE)
        screen.blit(birds_text, (WIDTH - birds_text.get_width() - 20, 60))
        
        # 绘制游戏状态
        if self.game_state == "aiming":
            # 绘制弹弓线
            pygame.draw.line(screen, BROWN, (self.slingshot.x, self.slingshot.y - 50), 
                           (self.current_bird.x, self.current_bird.y), 5)
            
            # 绘制弹道预测
            self.draw_trajectory()
        
        elif self.game_state == "level_complete":
            overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
            overlay.fill((0, 0, 0, 150))
            screen.blit(overlay, (0, 0))
            
            level_text = font.render(f"关卡 {self.level} 完成!", True, YELLOW)
            screen.blit(level_text, (WIDTH // 2 - level_text.get_width() // 2, HEIGHT // 2 - 50))
            
            next_text = small_font.render("准备进入下一关...", True, WHITE)
            screen.blit(next_text, (WIDTH // 2 - next_text.get_width() // 2, HEIGHT // 2 + 10))
        
        elif self.game_state == "game_over":
            overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
            overlay.fill((0, 0, 0, 150))
            screen.blit(overlay, (0, 0))
            
            game_over_text = font.render("游戏结束!", True, RED)
            screen.blit(game_over_text, (WIDTH // 2 - game_over_text.get_width() // 2, HEIGHT // 2 - 50))
            
            score_text = font.render(f"最终分数: {self.score}", True, YELLOW)
            screen.blit(score_text, (WIDTH // 2 - score_text.get_width() // 2, HEIGHT // 2))
            
            restart_text = small_font.render("按R键重新开始", True, WHITE)
            screen.blit(restart_text, (WIDTH // 2 - restart_text.get_width() // 2, HEIGHT // 2 + 50))
    
    def draw_trajectory(self):
        # 计算弹道预测
        start_x, start_y = self.current_bird.x, self.current_bird.y
        vx = (self.slingshot.x - self.current_bird.x) * 0.05
        vy = (self.slingshot.y - self.current_bird.y) * 0.05
        
        points = []
        for i in range(100):
            t = i * 0.5
            x = start_x + vx * t
            y = start_y + vy * t + 0.5 * GRAVITY * t * t
            
            if y > HEIGHT - 100:
                break
            
            points.append((int(x), int(y)))
        
        # 绘制弹道
        if len(points) > 1:
            pygame.draw.lines(screen, (255, 255, 255, 150), False, points, 2)
    
    def handle_event(self, event):
        if event.type == MOUSEBUTTONDOWN:
            if self.game_state == "ready" and event.button == 1:
                # 检查是否点击了小鸟
                if self.current_bird and math.sqrt((event.pos[0] - self.current_bird.x)**2 + 
                                                (event.pos[1] - self.current_bird.y)**2) < self.current_bird.radius:
                    self.game_state = "aiming"
                    self.slingshot.pulled = True
                    self.slingshot.pull_x = event.pos[0]
                    self.slingshot.pull_y = event.pos[1]
        
        elif event.type == MOUSEMOTION:
            if self.game_state == "aiming":
                self.slingshot.pull_x = event.pos[0]
                self.slingshot.pull_y = event.pos[1]
                
                # 限制拉回距离
                dx = self.slingshot.x - self.slingshot.pull_x
                dy = self.slingshot.y - self.slingshot.pull_y
                distance = math.sqrt(dx*dx + dy*dy)
                
                if distance > 150:
                    angle = math.atan2(dy, dx)
                    self.slingshot.pull_x = self.slingshot.x - 150 * math.cos(angle)
                    self.slingshot.pull_y = self.slingshot.y - 150 * math.sin(angle)
                
                # 更新小鸟位置
                self.current_bird.x = self.slingshot.pull_x
                self.current_bird.y = self.slingshot.pull_y
        
        elif event.type == MOUSEBUTTONUP:
            if self.game_state == "aiming" and event.button == 1:
                self.game_state = "launched"
                self.slingshot.pulled = False
                
                # 计算发射速度
                dx = self.slingshot.x - self.current_bird.x
                dy = self.slingshot.y - self.current_bird.y
                
                self.current_bird.vx = dx * 0.05
                self.current_bird.vy = dy * 0.05
                self.current_bird.launched = True
                self.current_bird.active = True
        
        elif event.type == KEYDOWN:
            if event.key == K_SPACE and self.game_state == "launched":
                # 使用特殊能力
                new_birds = self.current_bird.use_special_ability()
                if new_birds:
                    self.birds.extend(new_birds)
                    self.current_bird = new_birds[0]
            
            elif event.key == K_r and self.game_state == "game_over":
                # 重新开始游戏
                self.__init__()
    
    def next_bird(self):
        # 找到下一个未发射的小鸟
        for bird in self.birds:
            if not bird.launched:
                self.current_bird = bird
                self.current_bird.x = self.slingshot.x
                self.current_bird.y = self.slingshot.y - 50
                self.game_state = "ready"
                return True
        return False

# 主游戏循环
def main():
    game = Game()
    running = True
    
    while running:
        for event in pygame.event.get():
            if event.type == QUIT:
                running = False
            else:
                game.handle_event(event)
        
        # 更新游戏状态
        game.update()
        
        # 检查是否需要切换到下一只小鸟
        if game.game_state == "launched" and not game.current_bird.active:
            if not game.next_bird():
                game.game_state = "game_over"
        
        # 绘制
        game.draw()
        
        # 更新显示
        pygame.display.flip()
        
        # 控制帧率
        clock.tick(FPS)
    
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()

